package leetcode.搜索;

import java.util.Arrays;

/**
 * 下一个排列
 *
 * 实现获取下一个排列的函数，算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
 *
 * 如果不存在下一个更大的排列，则将数字重新排列成最小的排列（即升序排列）。
 *
 * 必须原地修改，只允许使用额外常数空间。
 *
 * 以下是一些例子，输入位于左侧列，其相应输出位于右侧列。
 * 1,2,3 → 1,3,2
 * 3,2,1 → 1,2,3
 * 1,1,5 → 1,5,1
 *
 */
public class Test31下一个排列 {

    public static void nextPermutation(int[] nums) {
        if (nums == null || nums.length <= 1) {
            return;
        }
        // 第一步：从最右边开始找到第一个递减的元素
        int i = nums.length - 2;
        while (i >= 0 && nums[i] >= nums[i + 1]) {
            i--;
        }
        // 现在i指向了第一个递减的元素
        if (i >= 0) {
            // 第二步：从 nums 的最右边开始寻找比 nums[i] 大的第一个元素并交换
            int j = nums.length - 1;
            while (i < j && nums[i] >= nums[j]) {
                j--;
            }
            // 现在 j 指向比 nums[i] 大的元素了，开始交换他们
            int temp = nums[j];
            nums[j] = nums[i];
            nums[i] = temp;
        }
        // 第三步：nums[i] 右边的元素一定都是逆序的，需要反转一下顺序
        // 这里包含一种特殊情况，若该排列已经是字典序中的最大了，
        // 则下一个序列应该是最小字典序，因此，直接在这里逆置即可
        int end = nums.length - 1;
        int start = i + 1;
        while (start < end) {
            int temp = nums[end];
            nums[end] = nums[start];
            nums[start] = temp;
            end--;
            start++;
        }
    }

    public static void main(String[] args) {
        int[] nums = {1,3,2};
        nextPermutation(nums);
        System.out.println(Arrays.toString(nums));
    }
}
